home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 4
/
Aminet 4 - November 1994.iso
/
aminet
/
comm
/
ums
/
ums109_1.lha
/
Tools
/
TopTen.LHA
/
TopTen
/
TopTen.mod
< prev
Wrap
Text File
|
1993-04-04
|
10KB
|
357 lines
(*-------------------------------------------------------------------------
:Program. TopTen
:Contents. Scans and analyses UMS message areas
:Author. Jan Geißler
:Address. fidonet: Jan Geissler@2:2407/106.5
:Address. usenet: jan@digit.stgt.sub.org
:Address. phone: +49 (7142) 44740
:Address. snail: Hermann-Rombach-Str. 17,
:Address. D-7120 (74321) Bietigheim-Biss.
:Author. Kai Bolay [kai]
:Address. Snail Mail: EMail:
:Address. Hoffmannstraße 168 UUCP: kai@amokle.stgt.sub.org
:Address. D-71229 Leonberg FIDO: 2:2407/106.3
:Copyright. Public Domain
:Language. Oberon-2
:Translator. Amiga Oberon V3.01 A+L
:Usage. USER/A,PASSWORD/A,GROUP/A
:History. v1.1 [jan] 19-Mar-93
:History. v1.2 [jan] 21-Mar-93 OddChk disabled while COPYing
:History. v2.0 [kai] 31-Mar-93 SINCE, MAXMSG, no VAL()
--------------------------------------------------------------------------- *)
MODULE TopTen;
(* IMPORT *)
IMPORT d: Dos,
s: SYSTEM,
NoGuru,
Break,
m: ums,
u: Utility,
str: Strings,
l: Lists,
e: Exec;
CONST copyright = "UMSTopTen 2.0 © Jan Geißler & Kai Bolay, Public Domain.\o$VER: UMSTopTen 2.0 (31.3.93)";
(* USAGE/CLI-PARAMS Const/Types/Vars*)
CONST
template = "USER/A,PASSWORD/A,GROUP/A,SINCE/K/N,MAXMSG/K/N";
usageErr = "Usage: %s\n%s\n";
TYPE
LONGPTR = UNTRACED POINTER TO LONGINT;
VAR
Args: STRUCT
user, password, group: e.STRPTR;
since, maxMsg: LONGPTR;
END;
RD: d.RDArgsPtr;
(* UMS Vars*)
VAR
msgNum,
login: LONGINT;
msgLen: LONGINT;
(* STATISTIC Consts/Types/Vars *)
CONST
separator = "---------------------------------------------------------------------------\n";
TYPE
UserProfile * = RECORD (l.Node)
name: e.STRING;
numMsgs: LONGINT;
numBytes: LONGINT;
END;
UserProfilePtr * = POINTER TO UserProfile;
SubjectProfile * = RECORD (l.Node)
name: e.STRING;
numMsgs: LONGINT;
numBytes: LONGINT;
END;
SubjectProfilePtr * = POINTER TO SubjectProfile;
VAR
nam: UserProfilePtr;
sub: SubjectProfilePtr;
from,
subject: e.STRING;
UserList: l.List;
SubjectList: l.List;
tenUsers: ARRAY 10 OF UserProfilePtr;
tenSubjects: ARRAY 10 OF SubjectProfilePtr;
numUsers,
numSubjects,
numMsgs,
numBytes: LONGINT;
i,c,x: LONGINT;
(* ---------------------------------------------------------------------------------- *)
(* PROC: AddName - Adds new user and/or increases "byte and message accounts" *)
PROCEDURE AddName;
VAR x,y: LONGINT;
no: UserProfilePtr;
ta: UserProfilePtr;
err: BOOLEAN;
non: l.NodePtr;
BEGIN
no := l.Head(UserList)(UserProfilePtr);
ta := l.Tail(UserList)(UserProfilePtr);
IF no#NIL THEN
WHILE (no#NIL) AND (no.name#from) DO
non := no; IF l.Next(non) THEN END;
no := non(UserProfilePtr);
END;
IF no#NIL THEN
(* Eintrag gefunden! *)
INC(no.numBytes,msgLen);
INC(no.numMsgs);
RETURN
END;
END;
NEW(no);
COPY(from,no.name);
no.numBytes := msgLen;
no.numMsgs := 1;
INC(numUsers);
l.AddTail(UserList,no);
END AddName;
(* PROC: SortUsers - Sorts the "User Top Ten" by number of messages *)
PROCEDURE SortUsers;
BEGIN
nam := l.Head(UserList)(UserProfilePtr);
FOR i := 1 TO numUsers DO
c := 0;
LOOP
IF (tenUsers[c]=NIL) OR ((c=9) AND (tenUsers[9].numMsgs<=nam.numMsgs)) THEN
tenUsers[c] := nam;
EXIT;
ELSE
IF tenUsers[c].numMsgs<=nam.numMsgs THEN
FOR x := 0 TO 9-c-1 DO
tenUsers[9-x] := tenUsers[9-x-1];
END;
tenUsers[c] := nam;
EXIT;
END;
END;
INC(c); IF c=10 THEN EXIT END;
END;
nam := nam.next(UserProfilePtr);
END;
END SortUsers;
(* PROC: AddSubject - Adds new subject and/or increases "byte and message account" *)
PROCEDURE AddSubject;
VAR x,y: LONGINT;
no: SubjectProfilePtr;
ta: SubjectProfilePtr;
err: BOOLEAN;
non: l.NodePtr;
BEGIN
no := l.Head(SubjectList)(SubjectProfilePtr);
ta := l.Tail(SubjectList)(SubjectProfilePtr);
IF no#NIL THEN
WHILE (no#NIL) AND (no.name#subject) DO
non := no; IF l.Next(non) THEN END;
no := non(SubjectProfilePtr);
END;
IF no#NIL THEN
(* Eintrag gefunden! *)
INC(no.numBytes,msgLen);
INC(no.numMsgs);
RETURN
END;
END;
NEW(no);
COPY(subject,no.name);
no.numBytes := msgLen;
no.numMsgs := 1;
INC(numSubjects);
l.AddTail(SubjectList,no);
END AddSubject;
(* PROC: SortSubject - Sorts the "Subject Top Ten" by number of messages *)
PROCEDURE SortSubjects;
BEGIN
sub := l.Head(SubjectList)(SubjectProfilePtr);
FOR i := 1 TO numSubjects DO
c := 0;
LOOP
IF (tenSubjects[c]=NIL) OR ((c=9) AND (tenSubjects[9].numMsgs<=sub.numMsgs)) THEN
tenSubjects[c] := sub;
EXIT;
ELSE
IF tenSubjects[c].numMsgs<=sub.numMsgs THEN
FOR x := 0 TO 9-c-1 DO
tenSubjects[9-x] := tenSubjects[9-x-1];
END;
tenSubjects[c] := sub;
EXIT;
END;
END;
INC(c); IF c=10 THEN EXIT END;
END;
sub := sub.next(SubjectProfilePtr);
END;
END SortSubjects;
(* PROC: GetArgs - Gets CLI arguments *)
PROCEDURE GetArgs*;
VAR
c: INTEGER;
match: e.STRPTR;
BEGIN
RD := d.ReadArgs (template,Args,NIL);
IF RD = NIL THEN d.PrintF (usageErr,s.ADR(copyright),s.ADR(template)); HALT (20) END;
IF Args.since # NIL THEN d.PrintF ("SINCE not implemented yet.\n"); HALT (20) END;
IF Args.maxMsg # NIL THEN d.PrintF ("MAXMSG not implemented yet.\n"); HALT (20) END;
END GetArgs;
(* PROC: StripRe - Strips "RE:" and leading spaces *)
PROCEDURE StripRe(VAR st:ARRAY OF CHAR);
VAR xy:e.STRING;
i: LONGINT;
BEGIN
COPY(st,xy); str.Upper(xy);
REPEAT
i := str.Occurs(xy,"RE:");
IF i#-1 THEN str.Delete(st,i,3); str.Delete(xy,i,3) END;
UNTIL i=-1;
WHILE (st[0]=" ") DO
str.Delete(st,0,1);
END;
END StripRe;
(* PROC: ScanData - Scans an UMS group *)
PROCEDURE ScanData;
VAR
p1,p2: m.STRPTR;
BEGIN
d.PrintF("Scanning data...\n");
msgNum := 0;
REPEAT
msgNum := m.UMSSearchTags(login,m.tagGroup, Args.group,
m.tagSearchLast,msgNum,
(* m.tagSearchPattern,1 *)
m.tagSearchQuick,1,u.done);
IF msgNum#0 THEN
IF ~m.ReadUMSMsgTags(login, m.tagRMsgNum,msgNum,
m.tagRReadHeader,0,
m.tagRFromName,s.ADR(p1),
m.tagRSubject,s.ADR(p2),
m.tagRTxtLength,s.ADR(msgLen),
m.tagRNoUpdate,0,u.done) THEN
d.PrintF("Cannot open msg!");
ELSE
INC(numMsgs); INC(numBytes,msgLen);
(* $OddChk- *)
COPY(p2^,subject); StripRe(subject);
COPY(p1^,from);
(* $OddChk= *)
AddName;
AddSubject;
m.FreeUMSMsg(login,msgNum);
END;
END;
UNTIL msgNum=0;
d.PrintF("done.\nProcessing data...\n");
SortUsers;
SortSubjects;
IF (numMsgs=0) THEN c := 0 ELSE c := (numBytes DIV numMsgs) END;
d.PrintF(separator);
d.PrintF("Area: %s\n",Args.group);
d.PrintF("Users: #%ld\n",numUsers);
d.PrintF("Messages: #%ld\n",numMsgs);
d.PrintF("Bytes: #%ld (av. %ld bytes/message)\n",numBytes,c);
d.PrintF(separator);
d.PrintF("TOP 10 - MOST MESSAGES\n");
d.PrintF(separator);
FOR i := 0 TO 9 DO
IF tenUsers[i]#NIL THEN
IF (tenUsers[i].numMsgs=0) THEN c := 0
ELSE c := tenUsers[i].numBytes DIV tenUsers[i].numMsgs
END;
IF (tenUsers[i].numMsgs=0) THEN x := 0 ELSE x := (tenUsers[i].numMsgs*100) DIV numMsgs END;
d.PrintF("%2.ld. %-30.28s (%3.ld msgs/%2.ld%%,%8.ld b.,%6.ld b./msg)\n",i+1,s.ADR(tenUsers[i].name),tenUsers[i].numMsgs,x,tenUsers[i].numBytes,c);
END;
END;
d.PrintF(separator);
d.PrintF("TOP 10 - SUBJECTS\n");
d.PrintF(separator);
FOR i := 0 TO 9 DO
IF tenSubjects[i]#NIL THEN
IF (tenSubjects[i].numMsgs=0) THEN c := 0
ELSE c := tenSubjects[i].numBytes DIV tenSubjects[i].numMsgs
END;
IF (tenSubjects[i].numMsgs=0) THEN x := 0 ELSE x := (tenSubjects[i].numMsgs*100) DIV numMsgs END;
d.PrintF("%2.ld. %-30.28s (%3.ld msgs/%2.ld%%,%8.ld b.,%6.ld b./msg)\n",i+1,s.ADR(tenSubjects[i].name),tenSubjects[i].numMsgs,x,tenSubjects[i].numBytes,c);
END;
END;
d.PrintF(separator);
END ScanData;
(* ---------------------------------------------------------------------------------- *)
(* MAIN: *)
BEGIN
GetArgs;
l.Init(SubjectList);
l.Init(UserList);
(* LOGIN *)
(* $OddChk- *)
login := m.Login(Args.user^,Args.password^);
(* $OddChk= *)
IF login=0 THEN d.PrintF("Login failed.\n"); HALT(20) END;
ScanData;
(* CLOSE: *)
CLOSE
IF login # 0 THEN m.Logout(login); login := 0 END;
IF RD # NIL THEN d.FreeArgs (RD); RD := NIL END;
END TopTen.